home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-02-27 | 7.6 KB | 311 lines | [TEXT/CWIE] |
- /* SK8 © 1997 Apple Computer, Inc.
- This code is protected under the current SK8 License
- See http://sk8.research.apple.com/ for more information
- Apple Research Laboratories
- */
-
-
- /*
- list
- a linked list that adheres to the SK8 collection protocol
-
- */
-
-
-
- public class list extends collection {
-
- // defining protected data members
- protected Object mValue;
- protected list mRest;
- protected boolean mIsEmpty;
-
-
- // Defining methods
-
- // constructor
- public list(){
- mIsEmpty = true;
- mValue = null;
- mRest = null;
- }
-
- // protected methods
- // subclasses should override checkvisitstate, newvisitstate, & newSibling
- protected void checkvisitstatetype(visitstate inState) {
- if ((inState != null) && (! (inState instanceof listvisitstate)))
- throw new IllegalArgumentException("Incompatable visitstate class passed");
- }
-
- protected visitstate newvisitstate(list inList, list inState){
- return new listvisitstate(inList, inState);}
- protected visitstate newvisitstate(list inList){
- return new listvisitstate(inList);}
-
- protected list newSibling() {return new list();}
- protected void swapValues(list inOther) {
- boolean theBool = inOther.mIsEmpty;
- inOther.mIsEmpty = this.mIsEmpty;
- this.mIsEmpty = theBool;
-
- Object theObj = inOther.mValue;
- inOther.mValue = this.mValue;
- this.mValue = theObj;
-
- //don't swap mRest! we want to maintain the order of the cells
- }
-
- public list copy() {
- list newCollection = new list();
- for(visitstate vs = this.initialvisitstate(); vs != null; vs = this.succeedingvisitstate(vs))
- newCollection.pushend(this.elementatvisitstate(vs));
- return newCollection;
- }
-
-
-
- //public collection protocol stuff
-
- /**
- ** initialvisitstate
- **/
- public visitstate initialvisitstate(){
- if (mIsEmpty == true) {
- return null;
- } else {
- return newvisitstate(this);
- }
- }
-
-
- /**
- ** isfinalvisitstate
- **/
-
- public boolean isfinalvisitstate(visitstate inState){
- checkvisitstatetype(inState);
- if (((listvisitstate)inState).mCell.mRest == null)
- return true;
- else
- return false;
- }
-
- /**
- ** succeedingvisitstate
- **/
- public visitstate succeedingvisitstate(visitstate inState) {
- checkvisitstatetype(inState);
-
- if (inState == null)
- throw new NullPointerException("Can't pass null visitstate.");
-
- if (isfinalvisitstate(inState))
- return null; // throw new collectionexception("A final visitstate has no succeeding visitstate.");
-
- return newvisitstate(this, ((listvisitstate)inState).mCell.mRest);
- }
-
-
-
- /**
- ** elementAtvisitstate
- **/
- public Object elementatvisitstate(visitstate inState) {
- checkvisitstatetype(inState);
- if (inState != null){
- return ((listvisitstate)inState).mCell.mValue;
- } else {
- return null;
- }
- }
-
-
-
- /**
- ** setelementatvisitstate
- **/
- public void setelementatvisitstate(visitstate inState, Object inElement) {
- checkvisitstatetype(inState);
- if (inState != null){
- ((listvisitstate)inState).mCell.mValue = inElement;
- }
- }
-
-
-
- /**
- ** removevisitstate
- **/
-
- public void removevisitstate(visitstate inState) {
- checkvisitstatetype(inState);
- if ((inState != null) && (!mIsEmpty)) {
- if (this == ((listvisitstate)inState).mCell) {
- //removing the first element! What we'll actually do is set the
- //car of the first cons cell to the car of the second, then remove
- //the second.
- if (mRest != null) {
- mValue = mRest.mValue;
- mRest = mRest.mRest;
- } else {
- mIsEmpty = true;
- }
- } else {
- //scan the list then remove the baddy
- list scanner = this;
- while ((scanner.mRest != null) && (scanner.mRest != ((listvisitstate)inState).mCell)) {
- scanner = scanner.mRest;
- }
- if (scanner.mRest == ((listvisitstate)inState).mCell) {
- scanner.mRest = scanner.mRest.mRest; //remove the baddy!
- }
- }
- }
- }
-
-
- /**
- ** insertatvisitstate
- **/
-
- public visitstate insertatvisitstate(visitstate inState, Object inElement) {
- return this.insertatvisitstate(inState, inElement, false);
- }
-
- public visitstate insertatvisitstate(visitstate inState,
- Object inElement, boolean inInsertAfter){
- checkvisitstatetype(inState);
- listvisitstate theVS = (listvisitstate)inState;
-
- if (mIsEmpty) {
- mValue = inElement;
- mIsEmpty = false;
- return newvisitstate(this);
-
- } else if (inState == null) {
- return null; // or should we throw an error?
-
- } else { //search the list for inState
- list theNewCell;
- if ((this == theVS.mCell)) { //if inState is the first element...
- theNewCell = newSibling(); //we insert after the first element
- theNewCell.mIsEmpty = false;
- theNewCell.mValue = inElement;
- theNewCell.mRest = this.mRest;
- this.mRest = theNewCell;
- if (!inInsertAfter){ //swap vals so the new values appear
- this.swapValues(theNewCell); //in front if necessary
- return newvisitstate(this);
- } else {
- return newvisitstate(this, theNewCell);
- }
-
- } else { //inState is not the first element
- list scanner = this; //so we scan down the list
- while ((scanner.mRest != null) && (scanner.mRest != theVS.mCell)) {
- scanner = scanner.mRest;
- }
- if (scanner.mRest == theVS.mCell) {
- //at this point, scanner points to the cell before the one inState refers to
- if (inInsertAfter)
- scanner = scanner.mRest;
- //now scanner points to the cell before the insertion
- theNewCell = newSibling();
- theNewCell.mIsEmpty = false;
- theNewCell.mValue = inElement;
- theNewCell.mRest = scanner.mRest;
- scanner.mRest = theNewCell;
- return newvisitstate(this, theNewCell);
- } else {
- throw new IllegalArgumentException("listvisitstate passed does not refer to this list");
- }
- }
- }
-
- }
-
-
- public int indexatvisitstate(visitstate inState){
- checkvisitstatetype(inState);
- if (mIsEmpty) {
- throw new RuntimeException("Cant get the index of an item from an empty list");
- } else {
- list scanner = this;
- int i = 1;
- while ((scanner != null) && (scanner != ((listvisitstate)inState).mCell)) {
- scanner = scanner.mRest;
- i++;
- }
- if (scanner == ((listvisitstate)inState).mCell){
- return i;
- } else {
- throw new IllegalArgumentException("passed listvisitstate is not for this list");
- }
- }
- }
-
-
-
- public visitstate visitstateatindex(int inIndex){
- if (inIndex <= 0) {
- throw new IndexOutOfBoundsException("collection index must be positive");
- } else {
- list scanner = this;
- while ((scanner != null) && (inIndex-- != 1)) {
- scanner = scanner.mRest;
- }
- if (scanner == null){
- throw new IndexOutOfBoundsException("index is greater than length of list");
- } else {
- return newvisitstate(this, scanner);;
- }
- }
- }
-
- public void printOut () { //for debugging, eh
- if (mValue != null){
- System.out.print(mValue.toString() + ", ");
- } else {
- System.out.print("null, ");
- }
- if (mRest != null)
- mRest.printOut();
- }
-
- public static list concatenate (list ll1, list ll2) {
- list newlist = new list();
-
- visitstate vs;
- vs = ll1.initialvisitstate();
- while (vs != null) {
- newlist.pushend(ll1.elementatvisitstate(vs));
- vs = ll1.succeedingvisitstate(vs);
- }
- vs = ll2.initialvisitstate();
- while (vs != null) {
- newlist.pushend(ll2.elementatvisitstate(vs));
- vs = ll2.succeedingvisitstate(vs);
- }
-
- return newlist;
- }
-
- //helpers
- //Added by AP 8/14
- public list rest() {
- return mRest;
- }
-
- public list reverse() {
- list outlist = new list();
- visitstate vs;
- vs = this.initialvisitstate();
- while (vs != null) {
- outlist.push(this.elementatvisitstate(vs));
- vs = this.succeedingvisitstate(vs);
- }
- return outlist;
- }
-
-
- }